package com.springbootblog.controller.fontend;

import com.rabbitmq.client.*;
import com.springbootblog.utils.RabbitUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/**
 * RabbitMQ部分接口
 * @className AboutController
 * @author camellia
 * @email 805795955@qq.com
 * @date 2024/01/01
 * @version 1.0
 */
@RequestMapping("java")
@RestController
public class RabbitMQController
{
    @Resource
    private RabbitTemplate rabbitTemplate;

    @GetMapping("rabbit/sendMsg")
    public void send(String message)
    {
        rabbitTemplate.convertAndSend("test_exchange", "test_queue_1", "hello world", new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                // message.getMessageProperties().setHeader("x-delay",1000*60);
                System.out.println("发送回调");
                return message;
            }
        });
        //rabbitTemplate.convertAndSend("test_exchange", "test_queue_1", "hello world");
    }

    /**
     * 自动确认监听 方法
     * @param message
     */
    // 这个注解标注的方法是不能有返回值的
    /*@RabbitListener(queues = "test_queue_1")
    public void receive(String message)
    {
        System.out.println("Received Message: " + message);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("消息接收时间:"+sdf.format(new Date()));
        System.out.println("接收到的消息:"+message);
    }//*/

    /**
     * 手动确认监听 方法
     * @param message   消息
     * @param channel   队列
     * @throws IOException
     */
    // 这个注解标注的方法是不能有返回值的
    @RabbitListener(queues = "test_queue_1", containerFactory = "rabbitListenerContainerFactory")
    public void receiveMessage(Message message, Channel channel) throws IOException
    {
        try
        {
            // 处理消息
            System.out.println("手动确认监听: " + new String(message.getBody()));

            // 确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
        catch (Exception e)
        {
            // 处理异常，可以选择重新将消息重新放入队列
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }//*/

    /*@GetMapping("rabbit/sendMsg")
    public void sendMsg(@RequestParam(defaultValue = "") String queueName, @RequestParam(defaultValue = "") String msg) throws IOException, TimeoutException
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("消息发送时间:"+sdf.format(new Date()));
        System.out.println(queueName);
        System.out.println(msg);
        rabbitTemplate.convertAndSend("test_exchange", queueName, msg, message -> {
            message.getMessageProperties().setHeader("x-delay",100);
            return message;
        });
        //获取TCP长连接
        Connection conn = RabbitUtils.getConnection();
        //创建通信“通道”，相当于TCP中的虚拟连接
        Channel channel = conn.createChannel();

        //创建队列,声明并创建一个队列，如果队列已存在，则使用这个队列
        //第一个参数：队列名称ID
        //第二个参数：是否持久化，false对应不持久化数据，MQ停掉数据就会丢失
        //第三个参数：是否队列私有化，false则代表所有消费者都可以访问，true代表只有第一次拥有它的消费者才能一直使用，其他消费者不让访问
        //第四个：是否自动删除,false代表连接停掉后不自动删除掉这个队列
        //其他额外的参数, null
        channel.queueDeclare("test_queue_2",false, false, false, null);

        String message = "hello白起666";
        //四个参数
        //exchange 交换机，暂时用不到，在后面进行发布订阅时才会用到
        //队列名称
        //额外的设置属性
        //最后一个参数是要传递的消息字节数组
        channel.basicPublish("", "test_queue_2", null,message.getBytes());
        channel.close();
        conn.close();
        System.out.println("===发送成功===");
    }//*/

    /*@GetMapping("rabbit/receiveMsg")
    public  void receiveMsg() throws IOException {
        //获取TCP长连接
        Connection conn = RabbitUtils.getConnection();
        //创建通信“通道”，相当于TCP中的虚拟连接
        Channel channel = conn.createChannel();

        //创建队列,声明并创建一个队列，如果队列已存在，则使用这个队列
        //第一个参数：队列名称ID
        //第二个参数：是否持久化，false对应不持久化数据，MQ停掉数据就会丢失
        //第三个参数：是否队列私有化，false则代表所有消费者都可以访问，true代表只有第一次拥有它的消费者才能一直使用，其他消费者不让访问
        //第四个：是否自动删除,false代表连接停掉后不自动删除掉这个队列
        //其他额外的参数, null
        channel.queueDeclare("test_queue_2",false, false, false, null);

        //从MQ服务器中获取数据

        //创建一个消息消费者
        //第一个参数：队列名
        //第二个参数代表是否自动确认收到消息，false代表手动编程来确认消息，这是MQ的推荐做法
        //第三个参数要传入DefaultConsumer的实现类
        channel.basicConsume("test_queue_2", false, new Reciver(channel));
    }//*/
}

/*class  Reciver extends DefaultConsumer {

    private Channel channel;
    //重写构造函数,Channel通道对象需要从外层传入，在handleDelivery中要用到
    public Reciver(Channel channel) {
        super(channel);
        this.channel = channel;
    }

    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

        String message = new String(body);
        System.out.println("消费者接收到的消息："+message);

        System.out.println("消息的TagId："+envelope.getDeliveryTag());
        //false只确认签收当前的消息，设置为true的时候则代表签收该消费者所有未签收的消息
        channel.basicAck(envelope.getDeliveryTag(), false);
    }
}//*/
